use std::error::Error;
use std::path::Path;
use serde_json;

const DEFAULT_CONFIG_DIR: str = "/etc/mrget";

const DEFAULT_CACHE_DIR: str = "/var/cache/mrget";

const DEFAULT_DATA_SOURCE_CACHE_AGING_TIME: u32 = 48 * 3600;    // 48 hours

const DEFAULT_SCORE_CACHE_AGING_TIME: u32 = 30 * 24 * 3600;     // 1 month

struct Config {
    use_cache: bool,
    cache_dir: Path,
    data_source_cache_aging_time: u32,
    score_cache_aging_time: u32,

    data_sources: &serde_json::Map<String, serde_json::Value>,
}

impl Config {
    fn new() -> Result<Self> {
        let fname = "/etc/mrget/mrget.conf";
        let data = JsonUtil::parse(fname)?;

        let var = "use-cache";
        let use_cache = JsonUtil::object_get_bool(data, var, true).expect("invalid value for \"{}\" property", var);

        let var = "cache-dir";
        let cache_dir = JsonUtil::object_get_path(data, var, DEFAULT_CACHE_DIR).expect("invalid value for \"{}\" property", var);

        let var = "data-source-cache-aging-time";
        let data_source_cache_aging_time = JsonUtil::object_get_u32(data, var, DEFAULT_DATA_SOURCE_CACHE_AGING_TIME)
                                                .expect("invalid value for \"{}\" property", var);

        let var = "score-cache-aging-time";
        let score_cache_aging_time = JsonUtil::object_get_u32(data, var, DEFAULT_SCORE_CACHE_AGING_TIME)
                                                .expect("invalid value for \"{}\" property", var);

        let data_sources = serde_json::json!({}).as_object();
        for entry in Util::ordered_read_dir_exclude("/etc/mrget", ["mrget.conf", "mrselect.conf"]) {
            let data = JsonUtil::parse(entry.path())?;
            let var = "data-sources";
            let t = JsonUtil::object_get_object(data, var).expect("invalid value for \"{}\" property in file \"{}\"", var, entry.path());
            data_sources.extend(t);
        }

        Ok(Config {
            use_cache, cache_dir, data_source_cache_aging_time, score_cache_aging_time,
            data_sources,
        })
    }

    fn use_cache(&self) -> bool {
        self.use_cache
    }

    fn get_cache_dir(&self) -> &str {
        &self.cache_dir
    }

    fn get_data_source_cache_aging_time(&self) -> u32 {
        self.data_source_cache_aging_time
    }

    fn get_score_cache_aging_time(&self) -> u32 {
        self.score_cache_aging_time
    }

    fn get_data_sources(&self) -> &serde_json::Map<String, serde_json::Value> {
        self.data_sources
    }
}
